package com.redoor.app.stake.basicdata.service.impl;

import com.redoor.app.stake.auth.commons.DatabaseServiceStatus;
import com.redoor.app.stake.auth.service.BaseUserService;
import com.redoor.app.stake.basicdata.commons.BasicDataStatus;
import com.redoor.app.stake.basicdata.dao.BaseStakeMapper;
import com.redoor.app.stake.basicdata.dao.BaseStationMapper;
import com.redoor.app.stake.basicdata.model.BaseParkingArea;
import com.redoor.app.stake.basicdata.model.BaseStake;
import com.redoor.app.stake.basicdata.model.BaseStation;
import com.redoor.app.stake.basicdata.model.BussinessTypeEnum;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseParkingAreaCriteria;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseStationCriteria;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseStationModifyBean;
import com.redoor.app.stake.basicdata.model.serviceModel.BaseStationServiceBean;
import com.redoor.app.stake.basicdata.mq.sendService.impl.SendMQServiceImpl;
import com.redoor.app.stake.basicdata.service.*;
import com.redoor.app.stake.common.utils.UUIDTool;
import com.redoornetwork.framework.core.exception.ServiceException;
import com.redoornetwork.framework.core.response.CoreStatus;
import com.redoornetwork.framework.mybatis.service.AbstractService;
import com.yotouch.app.stake.Consts;
import com.yotouch.app.stake.model.ChargingMonitor;
import com.yotouch.app.stake.model.CityData;
import com.yotouch.app.stake.model.Station;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by wangjunlei on 2018-02-12 10:08:10.
 */
@Service
public class BaseStationServiceImpl extends AbstractService<BaseStation, String> implements BaseStationService {

    private Logger logger = LoggerFactory.getLogger(BaseStationServiceImpl.class);

    @Autowired
    private BaseStationMapper baseStationMapper;

    @Autowired
    private BaseStationRedisService baseStationRedisService;

    @Autowired
    private BaseParkingAreaService baseParkingAreaService;

    @Autowired
    private SendMQServiceImpl mqService;

    @Autowired
    private BaseAssetOperationTrajectoryService baseAssetOperationTrajectoryService;

    @Autowired
    private BaseSystemOperationLogService baseSystemOperationLogService;

    @Autowired
    private BaseUserService userService;
    @Autowired
    private BaseStakeMapper baseStakeMapper;


    @Override
    public List<BaseStation> qryStationInfoDetail(BaseStationCriteria params) {
        return baseStationMapper.qryStationInfoDetail(params);
    }

    @Override
    public List<BaseStationServiceBean> qryStationServiceInfoDetail(BaseStationCriteria params) {
        return baseStationMapper.qryStationServiceInfoDetail(params);
    }

    @Override
    public List<Station> qryStationInfoDetailForHSF(BaseStationCriteria params) {
        return baseStationMapper.qryStationInfoDetailForHsf(params);
    }

    @Override
    public Station findByUuidForHsf(String uuid) {
        Station station = baseStationRedisService.getStationForHsf(uuid);
        if(null == station){
            BaseStationCriteria param = new BaseStationCriteria();
            param.setUuid(uuid);
            List<Station> stationList = qryStationInfoDetailForHSF(param);
            if(stationList != null && stationList.size() > 0 ){
                station = stationList.get(0);
                baseStationRedisService.HSetHsfStation(stationList);
            }
        }
        return station;
    }

    @Override
    public int qryStationInfoCnt(BaseStationCriteria params) {
        return baseStationMapper.qryStationInfoCnt(params);
    }

    @Override
    public BaseStation findById(String uuid) {
        BaseStation info = null;
        if(baseStationRedisService.isExistsStation(uuid)){
            info = (BaseStation)baseStationRedisService.getStationInfo(uuid);
        } else {
            info = baseStationMapper.selectByPrimaryKey(uuid);
            baseStationRedisService.modifyStationInfo(uuid,info);
        }
        return info;
    }

    @Override
    public Map<String, Object> qryStationStakeCntGroupByOperator(String stationuuid) {
        BaseStationCriteria params = new BaseStationCriteria();
        params.setUuid(stationuuid);
        return baseStationMapper.qryStationStakeCntGroupByOperator(params);
    }

    @Override
    public Map<String, Object> qryStationStakeTypeCnt(String stationuuid) {
        BaseStationCriteria params = new BaseStationCriteria();
        params.setUuid(stationuuid);
        return baseStationMapper.qryStationStakeTypeCnt(params);
    }

    @Override
    public boolean initHSFStationRedis() {
        baseStationRedisService.removeHsfStation("");
        BaseStationCriteria params = new BaseStationCriteria();
        int cnt = baseStationMapper.qryStationInfoCnt(params);
        int page = 1;
        int tatalPage = cnt % 100 == 0?cnt / 100 : cnt /100 +1;
        while (page < tatalPage) {
            params.setOffset((page-1)*100+1);
            params.setLimit(100);
            List<Station> list = baseStationMapper.qryStationInfoDetailForHsf(params);
            if(list !=null && list.size() >0 && baseStationRedisService.HSetHsfStation(list)){
                page ++ ;
            } else {
                return false;
            }
        }
        return true;
    }

    @Override
    public List<BaseParkingArea> qryParkingAreaListForStationUuid(String stationuuid) {
        BaseParkingAreaCriteria param = new BaseParkingAreaCriteria();
        param.setStationUuid(stationuuid);
        List<BaseParkingArea> parkingAreaList = baseStationRedisService.getParkingAreaList(stationuuid);
        if(null == parkingAreaList){
            parkingAreaList = baseParkingAreaService.qryParkingAreaInfoList(param);
            if(null != parkingAreaList){
                baseStationRedisService.setParkingAreaList(stationuuid,parkingAreaList);
            }
        }
        return parkingAreaList;
    }

    @Override
    public List<ChargingMonitor> qryStationinfoByConditionToHSF(Map<String, Object> map) {
        List<ChargingMonitor> list = this.baseStationMapper.qryStationinfoByConditionToHSF(map);
        return list;
    }

    @Override
    public int qryStationinfoByConditionTotalToHSF(Map<String, Object> map) {
        int StationCount = this.baseStationMapper.qryStationinfoByConditionTotalToHSF(map);
        return StationCount;
    }



    @Override
    public BaseStation qryStationBySataionNo(String stationNo) {
        BaseStation baseStation = new BaseStation();
        baseStation.setStationno(stationNo);
        baseStation.setStatus(Integer.valueOf(DatabaseServiceStatus.SERVICE_NORMAL_STATUS.getCode()));
        return this.baseStationMapper.selectOne(baseStation);
    }

    @Override
    public List<BaseStation> qryStationBygsNo(String gsNo) {
        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put("status", Integer.valueOf(DatabaseServiceStatus.SERVICE_NORMAL_STATUS.getCode()));
        map.put("gsNo", gsNo);
       return this.baseStationMapper.qryStationBygsNo(map);
    }

    @Override
    public List<CityData> qryCitysStationInfo(Map<String, Object> map) {
        return this.baseStationMapper.qryCitysStationInfo(map);
    }

    @Override
    public int qryStationCountByName(String name) {
        BaseStation baseStation = new BaseStation();
        baseStation.setStationname(name);
        baseStation.setStatus(Integer.valueOf(DatabaseServiceStatus.SERVICE_NORMAL_STATUS.getCode()));
        return this.baseStationMapper.selectCount(baseStation);
    }


    @Override
    public int deleteStation(String uuid,BussinessTypeEnum.TRACE_TYPE sourcetype) {

        //查询站下面是否绑定有桩
        BaseStake baseStake = new BaseStake();
        baseStake.setStationuuid(uuid);
        baseStake.setStatus(Integer.valueOf(DatabaseServiceStatus.SERVICE_NORMAL_STATUS.getCode()));
        int stakeCount = this.baseStakeMapper.selectCount(baseStake);
        //如果绑定已有桩则返回整形状态2;
        if(stakeCount > 0){
            return 2;
        }
        BaseStation oldStation = this.findById(uuid);
        if(baseStationRedisService.isExistsStation(uuid)){
            baseStationRedisService.deleteStationInfo(uuid);
        }
        if(oldStation == null){
            throw new ServiceException(BasicDataStatus.STATION_IS_NOTEXISTS);
        }

        int result = baseStationMapper.deleteByPrimaryKey(uuid);

        if (result > 0) {
            sendStationMQ(null,oldStation,BussinessTypeEnum.TAG_TYPE.DELETE.getName());
            baseAssetOperationTrajectoryService.addTraceLog(uuid,BussinessTypeEnum.TAG_TYPE.DELETE.getName(),BussinessTypeEnum.TRACE_BUSINESS_TYPE.STATION,sourcetype,"",oldStation,null);
            baseSystemOperationLogService.addSystemOperationLog(BussinessTypeEnum.WEB_OPERATOR_TYPE.STATION, BussinessTypeEnum.TAG_TYPE.DELETE,uuid,"",true);
        }
        //删除成功返回整形状态1
        if(result > 0){
            return 1;
            //其他为0
        }else{
            return 0;
        }
    }

    @Override
    public String saveStation(BaseStation info,BussinessTypeEnum.TRACE_TYPE sourcetype) {
        if (null == info) {
            throw new ServiceException(CoreStatus.SERVER_INTERNAL_ERROR);
        }
        BaseStation oldStation = this.findById(info.getUuid());
        if(oldStation != null){
            throw new ServiceException(BasicDataStatus.STATION_IS_EXISTS);
        }
        String orgcode = info.getPartorgcode();
        if(StringUtils.isEmpty(orgcode)){
            orgcode = info.getCityorgcode();
        }
        if(StringUtils.isEmpty(orgcode)){
            throw new ServiceException(BasicDataStatus.STATION_ORG_NOT_EXISTS);
        }
        if(StringUtils.isEmpty(info.getDistrictcode())){
            throw new ServiceException(BasicDataStatus.STATION_DISTRICT_NOT_EXISTS);
        }
        String stationNo = baseStationRedisService.getOutStationNo(info.getDistrictcode());
        if(StringUtils.isEmpty(stationNo)){
            stationNo = System.currentTimeMillis()+"";
        }
        info.setStationno(stationNo);
        info.setOutstationno(stationNo);
        info.setUuid(UUIDTool.getUUID());
        info.setCreatedat(new Date());
        info.setCreatoruuid(this.userService.getShiroUserUuid());
        int result = baseStationMapper.insert(info);
        String uuid = info.getUuid();
        if (result > 0) {
            baseStationRedisService.modifyStationInfo(uuid,info);
            sendStationMQ(info,oldStation,BussinessTypeEnum.TAG_TYPE.ADD.getName());
            baseAssetOperationTrajectoryService.addTraceLog(info.getUuid(),BussinessTypeEnum.TAG_TYPE.ADD.getName(),BussinessTypeEnum.TRACE_BUSINESS_TYPE.STATION,sourcetype,"",oldStation,info);
            baseSystemOperationLogService.addSystemOperationLog(BussinessTypeEnum.WEB_OPERATOR_TYPE.STATION, BussinessTypeEnum.TAG_TYPE.ADD,info.getUuid(),"",true);
        }

        return uuid;
    }

    @Override
    public int updateBySelective(BaseStation info,BussinessTypeEnum.TRACE_TYPE sourcetype) {
        return updateBySelective(info,sourcetype,null);
    }

    @Override
    public int updateBySelective(BaseStation info, BussinessTypeEnum.TRACE_TYPE sourcetype, String operatoruuid) {
        if (null == info) {
            throw new ServiceException(BasicDataStatus.STATION_IS_NOTEXISTS);
        }
        BaseStation oldStation = this.findById(info.getUuid());
        if(oldStation == null){
            throw new ServiceException(BasicDataStatus.STATION_IS_NOTEXISTS);
        }

        if(!mqService.checkObjectChange(oldStation,info)){
            throw new ServiceException(BasicDataStatus.STATION_NOT_CHANGE);
        }

        baseStationRedisService.modifyStationInfo(info.getUuid(),info);
        baseStationMapper.updateByPrimaryKeySelective(info);

        sendStationMQ(info,oldStation,BussinessTypeEnum.TAG_TYPE.UPDATE.getName());
        baseAssetOperationTrajectoryService.addTraceLog(info.getUuid(),BussinessTypeEnum.TAG_TYPE.UPDATE.getName(),BussinessTypeEnum.TRACE_BUSINESS_TYPE.STATION,sourcetype,operatoruuid,oldStation,info);
        baseSystemOperationLogService.addSystemOperationLog(BussinessTypeEnum.WEB_OPERATOR_TYPE.STATION, BussinessTypeEnum.TAG_TYPE.UPDATE,info.getUuid(),"",true);
        return 1;
    }

    @Transactional(rollbackFor=RuntimeException.class)
    @Override
    public int modifyStationAndParkingArea(BaseStationModifyBean baseStation, BussinessTypeEnum.TRACE_TYPE sourcetype) {
        if(baseStation==null){
            throw new ServiceException(BasicDataStatus.PARAM_IS_EMPTY);
        }

        List<BaseParkingArea> list = baseStation.getParkingAreaList();

        BaseStation baseStationInfo = baseStation.getStation();
        String stationuuid;
        if(!StringUtils.isEmpty(baseStationInfo.getUuid())){
            try{
                baseStationInfo.setUpdatedat(new Date());
                baseStationInfo.setUpdateruuid(this.userService.getShiroUserUuid());
                updateBySelective(baseStationInfo,sourcetype);
            } catch (ServiceException se) {
                if(se.getStatus() != BasicDataStatus.STATION_NOT_CHANGE){
                    throw se;
                }
            }
            stationuuid = baseStationInfo.getUuid();
        } else {
            baseStationInfo.setStatus(Consts.STATUS_NORMAL);
            stationuuid = saveStation(baseStationInfo,sourcetype);
        }
        if(list != null && list.size() > 0){
            for(BaseParkingArea area:list){
                area.setStationuuid(stationuuid);
                if(!StringUtils.isEmpty(area.getUuid())){
                    area.setUpdatedat(new Date());
                    area.setUpdateruuid(userService.getShiroUserUuid());
                    baseParkingAreaService.updateBySelective(area);
                } else {
                    area.setStatus(Consts.STATUS_NORMAL);
                    area.setUuid(UUIDTool.getUUID());
                    area.setCreatedat(new Date());
                    area.setCreatoruuid(userService.getShiroUserUuid());
                    baseParkingAreaService.save(area);
                }
            }
            baseStationRedisService.removeParkingAreaList(stationuuid);
        }
        return 1;
    }

    /**
     * 发送站点MQ
     * @param newStation
     * @param oldStation
     * @param tag
     * @return
     */
    public boolean sendStationMQ(BaseStation newStation,BaseStation oldStation,String tag){
        if (newStation == null && oldStation != null && "delete".equalsIgnoreCase(tag)) {
            newStation = new BaseStation();
            mqService.sendMessage("STATION_OPERATING","DELETE",newStation.getStationno(),oldStation.getUuid(), BussinessTypeEnum.MQ_BUSINESS_TYPE.STATION);
            return true;
        } else if (newStation != null && oldStation == null && "add".equalsIgnoreCase(tag)){
            mqService.sendMessage("STATION_OPERATING","ADD",newStation.getStationno(),newStation.getUuid(),BussinessTypeEnum.MQ_BUSINESS_TYPE.STATION);
            return true;
        } else if (newStation != null && oldStation != null && "update".equalsIgnoreCase(tag)){
            //根据配置的属性判断是否需要发送MQ
            if(mqService.needSendMQ(oldStation,newStation,"1000000001")){
                mqService.sendMessage("STATION_OPERATING","UPDATE",newStation.getStationno(),newStation.getUuid(),BussinessTypeEnum.MQ_BUSINESS_TYPE.STATION);
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}
